package com.twang.stock.service.jinyan;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.twang.stock.Entity.ShiShiData;
import com.twang.stock.common.DateUtil;
import com.twang.stock.common.http.HtmlTools;
import com.twang.stock.config.StockMsgSender;
import com.twang.stock.dto.EmailMessage;
import com.twang.stock.dto.StockMinutesMessage;
import com.twang.stock.entity.CompanyStock;
import com.twang.stock.entity.CompanyStockMinutes;
import com.twang.stock.mapper.CompanyStockMapper;
import com.twang.stock.mapper.CompanyStockMinutesMapper;
import com.twang.stock.redis.RedisUtil;
import com.twang.stock.threadPool.AsycTaskExecutorConfig;
import com.twang.stock.utils.date.DateUtils;
import com.twang.stock.utils.date.HolidayCopy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class StockMinutesService {


    @Autowired
    private AsycTaskExecutorConfig asycTaskExecutorConfig;

    @Autowired
    private RedisUtil redisUtil;

    @Resource
    private CompanyStockMinutesMapper companyStockMinutesMapper;

    @Resource
    private CompanyStockMapper companyStockMapper;
    @Resource
    private CommonService commonService;


    @Autowired
    private StockMsgSender stockMsgSender;

    /**
     * 读取数据
     * @param stockMinutesMessage
     * @return
     * @throws Exception
     */
    public void createStockMinutesDataByCode(StockMinutesMessage stockMinutesMessage) throws Exception {
        log.info("==================> createStockMinutesDataByCode start code={}",stockMinutesMessage.getCode());
       // List<ShiShiData> shiShiDataList= stockMinutesMessage.getDataList();
        List<ShiShiData> shiShiDataList = HtmlTools.getGpdatas(Lists.newArrayList(stockMinutesMessage.getCode()));
        if(CollectionUtils.isEmpty(shiShiDataList)){
            return;
        }
        if(CollectionUtils.isNotEmpty(shiShiDataList)) {
            List<CompanyStockMinutes> companyStockMinutesList = Lists.newArrayList();
            List<CompanyStockMinutes> update = Lists.newArrayList();

            shiShiDataList.stream().forEach(shiShiData -> {
                CompanyStockMinutes companyStockMinutes = new CompanyStockMinutes();
                companyStockMinutes.setDate(DateUtil.getToday().substring(0, 8));
                //companyStockMinutes.setMinutes(HolidayCopy.getHHmmss().substring(8, 12));
                companyStockMinutes.setMinutes(stockMinutesMessage.getMinutes());
                insertData(companyStockMinutesList, update, companyStockMinutes, shiShiData);
            });
            //批量插入
            insertBatch(companyStockMinutesList);
            updateBatch(update);
        }
    }

    public void insertBatch(List<CompanyStockMinutes> companyStockMinutes) {
        final int batchSize = 1000;
        for (int i = 0; i < companyStockMinutes.size(); i += batchSize) {
            int end = Math.min(i + batchSize, companyStockMinutes.size());
            List<CompanyStockMinutes> batch = companyStockMinutes.subList(i, end);
            int num=companyStockMinutesMapper.insertBatch(batch);
            log.info(">>>>>>>>>>>> insertBatch num={}",num);
        }
    }

    public void updateBatch(List<CompanyStockMinutes> companyStockMinutes) {
        final int batchSize = 1000;
        for (int i = 0; i < companyStockMinutes.size(); i += batchSize) {
            int end = Math.min(i + batchSize, companyStockMinutes.size());
            List<CompanyStockMinutes> batch = companyStockMinutes.subList(i, end);
           int num= companyStockMinutesMapper.updateBatch(batch);
            log.info(">>>>>>>>>>>> updateBatch num={}",num);

        }
    }

    /**
     *
     * @param companyStockMinutes
     * @param shiShiData
     */
    private void insertData(List<CompanyStockMinutes> companyStockMinutesList,List<CompanyStockMinutes> update, CompanyStockMinutes companyStockMinutes, ShiShiData shiShiData) {
        companyStockMinutes.setCompanyCode(shiShiData.getCode());
        companyStockMinutes.setCompanyName(shiShiData.getGpname());
        if(shiShiData.getGptime().startsWith("15")||shiShiData.getGptime().startsWith("16")||shiShiData.getGptime().startsWith("17")){
            shiShiData.setGptime("1500");
        }
        companyStockMinutes.setMinutes(shiShiData.getGptime());
        companyStockMinutes.setDate(shiShiData.getGpdate());

        //排除该时段的计算
        List<String> minutes = Lists.newArrayList( "0929");
        if (StringUtils.isNotBlank(companyStockMinutes.getMinutes()) && minutes.contains(companyStockMinutes.getMinutes())) {
            log.info("该时间段不计算数据 {}", companyStockMinutes.getMinutes());
            return ;
        }
        if (DateUtils.JudgeTime("09:26:00", "09:29:00")) {
            if (StringUtils.isNotBlank(companyStockMinutes.getMinutes())) {
                log.info("该时间9:00-09:30段不计算数据 {}", companyStockMinutes.getMinutes());
                return ;
            }
        }
        companyStockMinutes.setPrice(new BigDecimal(shiShiData.getPrice()).setScale(2, BigDecimal.ROUND_HALF_UP));
        companyStockMinutes.setTradeSum(new BigDecimal(shiShiData.getAmount()).setScale(2, BigDecimal.ROUND_HALF_UP));
        companyStockMinutes.setTradeVol(new BigDecimal(shiShiData.getSumvol()).setScale(2, BigDecimal.ROUND_HALF_UP));
        companyStockMinutes.setZhangDie(shiShiData.getZhangdie());
        companyStockMinutes.setCreateTime(new Date());
        try {
            CompanyStockMinutes temp = new CompanyStockMinutes();
            temp.setDate(companyStockMinutes.getDate());
            temp.setMinutes(companyStockMinutes.getMinutes());
            temp.setCompanyCode(companyStockMinutes.getCompanyCode());
            if (CollectionUtils.isNotEmpty(companyStockMinutesMapper.select(temp))) {
                companyStockMinutesMapper.delete(temp);
            }
            try {
                //更新分钟量能
                Example example = new Example(CompanyStockMinutes.class);
                Example.Criteria criteria = example.createCriteria();
                criteria.andEqualTo("date", companyStockMinutes.getDate());
                criteria.andEqualTo("companyCode", companyStockMinutes.getCompanyCode());
                example.orderBy("id").desc();
                List<CompanyStockMinutes> list = companyStockMinutesMapper.selectByExample(example);
                if (CollectionUtils.isNotEmpty(list)) {
                    CompanyStockMinutes last = list.get(0);

                    if (null == last) {
                        companyStockMinutes.setVol(BigDecimal.ZERO);
                        companyStockMinutes.setAmount(BigDecimal.ZERO);
                        companyStockMinutes.setCreateTime(new Date());
                    } else {
                        companyStockMinutes.setVol(companyStockMinutes.getTradeVol().subtract(last.getTradeVol()).setScale(2, BigDecimal.ROUND_HALF_UP));
                        companyStockMinutes.setAmount(companyStockMinutes.getTradeSum().subtract(last.getTradeSum()));
                        companyStockMinutes.setCreateTime(new Date());
                    }
                    //判断分时量能的大小，做预警
                    asycTaskExecutorConfig.taskQueueExecutor().execute(() -> {
                        try {
                            warn(companyStockMinutes);
                        } catch (Exception e) {
                            log.error("预警发生异常", e);
                        }
                    });
                }
            } catch (Exception e) {
                log.error("更新分钟量能  异常 {}", e);
            }
//            Example example = new Example(CompanyStockMinutes.class);
//            Example.Criteria criteria = example.createCriteria();
//            criteria.andEqualTo("date", companyStockMinutes.getDate());
//            criteria.andEqualTo("companyCode", companyStockMinutes.getCompanyCode());
//            criteria.andEqualTo("minutes", companyStockMinutes.getMinutes());
//            example.orderBy("id").desc();
//            List<CompanyStockMinutes> list = companyStockMinutesMapper.selectByExample(example);
           // if (CollectionUtils.isNotEmpty(list)) {
          //      CompanyStockMinutes last = list.get(0);
            //    companyStockMinutes.setId(last.getId());
           //     //companyStockMinutesMapper.updateByPrimaryKey(companyStockMinutes);
           //     update.add(companyStockMinutes);
          //  }else{
                companyStockMinutesList.add(companyStockMinutes);
                //companyStockMinutesMapper.insert(companyStockMinutes);
           // }

        } catch (Exception e) {
            log.error("Exception={}",e.getMessage());
        }finally {
            if(DateUtils.JudgeTime("09:59:00", "10:01:00")){
                String today30MinVolKey_ = "today30MinVol_" + companyStockMinutes.getCompanyCode() + "_" + HolidayCopy.getRealToday();
                redisUtil.del(today30MinVolKey_);
                log.info("缓存KEY删除成功：{}",today30MinVolKey_);
            }
        }
    }


    /**
     * 自选预警
     * @param companyStockMinutes
     */
    private void warn(CompanyStockMinutes companyStockMinutes) {
        List<String> ids= Arrays.asList(commonService.getValue("warn_ID").toString().split(","));
        for(String id:ids) {
            CompanyStock paramCount = new CompanyStock();
            paramCount.setCompanyCode(companyStockMinutes.getCompanyCode());
            paramCount.setUserId(Integer.valueOf(id));
           if (companyStockMapper.selectCount(paramCount) > 0) {
                List<String> dates = companyStockMinutesMapper.queryDates();
                /** 昨天 */
                String date = dates.get(dates.size() - 2);
                BigDecimal yestoDayMaxVol = getMaxVol(date, companyStockMinutes.getCompanyCode());
                if (companyStockMinutes.getVol().compareTo(yestoDayMaxVol) > 0) {
                    CompanyStock info = companyStockMapper.selectOne(paramCount);
                    String str = String.format("个股异动：【涨跌幅：%s 】time=%s  vol=%s  昨日vol=%s ！ 关联逻辑：%s ", companyStockMinutes.getZhangDie(), companyStockMinutes.getMinutes(), companyStockMinutes.getVol(), yestoDayMaxVol, null==info?"":info.getStockDesc());

                    EmailMessage emailMessage=new EmailMessage();
                    emailMessage.setCode(companyStockMinutes.getCompanyCode());
                    emailMessage.setName(companyStockMinutes.getCompanyName());
                    emailMessage.setMessage(str);
                    emailMessage.setUserId(Long.valueOf(id));
                    emailMessage.setType("1");
                    log.info(">>>>>>>>>>> 异动预警 emailMessage={}",JSONObject.toJSONString(emailMessage));
                    stockMsgSender.sendEmailMessage(JSONObject.toJSONString(emailMessage));
                }
           }
        }
    }
    /**
     * 获取最大的Vol
     * @param date
     * @param code
     * @return
     */
    public BigDecimal getMaxVol(String date, String code){
        Example example = new Example(CompanyStockMinutes.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("companyCode", code);
        criteria.andEqualTo("date", date);
        criteria.andNotIn("minutes", Lists.newArrayList(commonService.getValue(CommonService.UtilsKey.minutes_无效时分).split(",")));
        example.orderBy("id").asc();
        List<CompanyStockMinutes> companyStockMinutes = companyStockMinutesMapper.selectByExample(example);
        BigDecimal val = companyStockMinutes.stream().filter(stock -> stock.getVol() != null).map(CompanyStockMinutes::getVol).max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
        return val;
    }
}
